<?php
class DbUtils {
  public static function createResInst() {
    $result = new stdClass();
    $result->d = array();
    $result->c = NULL;
    $result->o = 'id';
    $result->q = 'ASC';
    $result->p = 1;
    $result->s = 0;
    $result->t = 0;
    return $result;
  }
  
  public static function createPdoInst() {
    require_once dirname(__FILE__) . '/metadata.php';
    require_once dirname(__FILE__) . '/config.php';
    try {
      $host = DB_HOST;
      $login = DB_LOGIN;
      $pass = DB_PASS;
      $db = DB_NAME;
      $myPdo = new PDO ("mysql:host=$host", $login, $pass);
      $myPdo->exec("USE $db");
      $myPdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      return $myPdo;
    } catch (PDOException $e) {
      echo ERROR_SIGN . $e->getMessage();
    }
    return NULL;
  }
  
  public static function get($myPdo, $table, $cond_vals, $order, $queue, $page, $size, $opts) {
    $select_expr = ($opts != NULL && isset($opts->select_expr)) ? $opts->select_expr : '*';
    $join_expr = ($opts != NULL && isset($opts->join_expr)) ? $opts->join_expr : NULL;
    $group_expr = ($opts != NULL && isset($opts->group_expr)) ? $opts->group_expr : '';
    
    $sql = "SELECT $select_expr FROM $table AS t ";
    if (isset($join_expr) && $join_expr != NULL) {
      $sql .= "$join_expr ";
    }
    $sql .= (($cond_vals != NULL && $cond_vals->c && !empty($cond_vals->c)) ? "WHERE $cond_vals->c " : '') . " " . $group_expr . " " . (($opts && isset($opts->groupby )) ? " $opts->groupby "  : ' ') . (($order && $queue) ? "ORDER BY $order $queue " : '') . (($page && $size) ? 'LIMIT :from, :limit' : '');
    if ($opts != NULL && isset($opts->debug)) {
      echo $sql;
    }
    $stmt = $myPdo->prepare($sql);
    if ($cond_vals != NULL && isset($cond_vals->v)) {
      foreach ($cond_vals->v as $key => &$value) {
        $stmt->bindParam($key, $value);
      }
    }
    if ($page && $size) {
    	$from = ($page - 1) * $size;
      $stmt->bindParam(':from', $from, PDO::PARAM_INT);
      $stmt->bindParam(':limit', $size, PDO::PARAM_INT);
    }
    $stmt->execute();
    
    $data = array();
    $i = 0;
    while ($i < $stmt->rowCount()) {
      $data[] = $stmt->fetch(PDO::FETCH_OBJ);
      $i++;
    }
    
    $result = DbUtils::createResInst();
    $result->d = $data;
    $result->c = $cond_vals;
    $result->o = $order;
    $result->q = $queue;
    $result->p = $page;
    $result->s = $size;
    if ($page && $size) {
      $sql = substr($sql, 0, strrpos($sql, 'LIMIT'));
      $stmt = $myPdo->prepare($sql);
      if ($cond_vals != NULL && isset($cond_vals->v)) {
        foreach ($cond_vals->v as $key => &$value) {
          $stmt->bindParam($key, $value);
        }
      }
      $stmt->execute();
      $result->t = $stmt->rowCount();
    } else {
      $result->t = $stmt->rowCount();
    }
    return $result;
  }
  
  public static function _toArray($table, $obj) {
    $arr = array();
    
    require_once dirname(__FILE__) . '/db/_orm/orm.inc.php';
    $orm = classToOrm($table);
    if ($orm) {
      $obj = $orm->toObj($obj);
    }
    foreach ($obj as $key => $value) {
      if (substr($key, 0, 1) == '_') {
        continue;
      }
      
      if ((gettype($value) == 'NULL') && is_null($value)) {
        $value = 0;
      }
//      if ((gettype($value) == 'boolean') && empty($value)) {
//        $value = 0;
//      }
      $tmp = new stdClass();
      $tmp->key = $key;
      $tmp->value = $value;
      $arr[] = $tmp;
    }
    return $arr;
  }
  
  public static function add($myPdo, $table, $obj) {
    $arr = DbUtils::_toArray($table, $obj);
    unset($obj->id);
    $args = array();
    $sql = "INSERT INTO `$table` (`id`, ";
    $val = "(NULL, ";
    foreach ($arr as $idx => $tmp) {
      $args[] = $tmp->value;
      $sql .= "`$tmp->key`";
      $val .= "?";
      
      if ($idx < (count($arr) - 1)) {
        $sql .= ', ';
        $val .= ', ';
      } else {
        $sql .= ') ';
        $val .= ')';
      }
    }
    $sql .= "VALUE $val";
    $stmt = $myPdo->prepare($sql);
    $stmt->execute($args);
  }
  
  public static function update($myPdo, $table, $obj) {
    $obj2 = clone $obj;
    $arr = DbUtils::_toArray($table, $obj2);
    $id = $obj2->id;
    unset($obj2->id);
    $args = array();
    $sql = "UPDATE `$table` SET ";
    foreach ($arr as $idx => $tmp) {
      $args[] = $tmp->value;
      $sql .= "`$tmp->key` = ?";
      
      if ($idx < (count($arr) - 1)) {
        $sql .= ', ';
      }
    }
    $args[] = $id;
    $sql .= " WHERE id = ?";
    $stmt = $myPdo->prepare($sql);
    $stmt->execute($args);
  }
  
  public static function delete($myPdo, $table, $obj) {
    $args = array($obj->id);
    $cond = 'id = ?';
    $sql = "DELETE FROM `$table` WHERE $cond";
    $stmt = $myPdo->prepare($sql);
    $stmt->execute($args);
  }
  
  public static function deleteByCond($myPdo, $table, $cond_vals) {
    $cond = ($cond_vals != NULL && isset($cond_vals->c) && !empty($cond_vals->c)) ? "$cond_vals->c " : '';
    $args = ($cond_vals != NULL && isset($cond_vals->v)) ? $cond_vals->v : array();
    
    if (!empty($cond) && count($args) > 0) { 
      $sql = "DELETE FROM `$table` WHERE $cond";
      $stmt = $myPdo->prepare($sql);
      $stmt->execute($args);
    }
  }
  
  public static function deleteByCondAdv($myPdo, $table, $cond_vals, $opts) {
    $join_expr = ($opts != NULL && isset($opts->join_expr)) ? $opts->join_expr : NULL;
    
    $cond = ($cond_vals != NULL && isset($cond_vals->c) && !empty($cond_vals->c)) ? "$cond_vals->c " : '';
    $args = ($cond_vals != NULL && isset($cond_vals->v)) ? $cond_vals->v : array();
    
    if (!empty($cond) && count($args) > 0) { 
      $sql = "DELETE t.* FROM `$table` AS t " . ((isset($join_expr) && $join_expr != NULL) ? "$join_expr " : '') . "WHERE $cond"; 
      $stmt = $myPdo->prepare($sql);
      $stmt->execute($args);
    }
  }
}
?>